home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CICA 1993 April
/
CICA MS Windows - April 1993.iso
/
unzipped
/
programr
/
wincap
/
dibutil.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-11-05
|
19KB
|
679 lines
/*
* dibutil.c
*
* Source file for Device-Independent Bitmap (DIB) API. Provides
* the following functions:
*
* FindDIBBits() - Sets pointer to the DIB bits
* DIBWidth() - Gets the width of the DIB
* DIBHeight() - Gets the height of the DIB
* PaletteSize() - Calculates the buffer size required by a palette
* DIBNumColors() - Calculates number of colors in the DIB's color table
* CreateDIBPalette() - Creates a palette from a DIB
* DIBToBitmap() - Creates a bitmap from a DIB
* BitmapToDIB() - Creates a DIB from a bitmap
*
* Development Team: Mark Bader
* Patrick Schreiber
* Garrett Mcauliffe
* Eric Flo
* Tony Claflin
*
* Written by Microsoft Product Support Services, Developer Support.
* Copyright (c) 1991 Microsoft Corporation. All rights reserved.
*/
/* header files */
#include <windows.h>
#include <assert.h>
#include "dibutil.h"
/*************************************************************************
*
* FindDIBBits()
*
* Parameter:
*
* LPSTR lpbi - pointer to packed-DIB memory block
*
* Return Value:
*
* LPSTR - pointer to the DIB bits
*
* Description:
*
* This function calculates the address of the DIB's bits and returns a
* pointer to the DIB bits.
*
************************************************************************/
LPSTR FindDIBBits(LPSTR lpbi)
{
return (lpbi + *(LPDWORD)lpbi + PaletteSize(lpbi));
}
/*************************************************************************
*
* DIBWidth()
*
* Parameter:
*
* LPSTR lpbi - pointer to packed-DIB memory block
*
* Return Value:
*
* DWORD - width of the DIB
*
* Description:
*
* This function gets the width of the DIB from the BITMAPINFOHEADER
* width field if it is a Windows 3.0-style DIB or from the BITMAPCOREHEADER
* width field if it is an OS/2-style DIB.
*
************************************************************************/
DWORD DIBWidth(LPSTR lpDIB)
{
LPBITMAPINFOHEADER lpbmi; // pointer to a Win 3.0-style DIB
LPBITMAPCOREHEADER lpbmc; // pointer to an OS/2-style DIB
/* point to the header (whether Win 3.0 and OS/2) */
lpbmi = (LPBITMAPINFOHEADER)lpDIB;
lpbmc = (LPBITMAPCOREHEADER)lpDIB;
/* return the DIB width if it is a Win 3.0 DIB */
if (lpbmi->biSize == sizeof(BITMAPINFOHEADER))
return lpbmi->biWidth;
else /* it is an OS/2 DIB, so return its width */
return (DWORD)lpbmc->bcWidth;
}
/*************************************************************************
*
* DIBHeight()
*
* Parameter:
*
* LPSTR lpbi - pointer to packed-DIB memory block
*
* Return Value:
*
* DWORD - height of the DIB
*
* Description:
*
* This function gets the height of the DIB from the BITMAPINFOHEADER
* height field if it is a Windows 3.0-style DIB or from the BITMAPCOREHEADER
* height field if it is an OS/2-style DIB.
*
************************************************************************/
DWORD DIBHeight(LPSTR lpDIB)
{
LPBITMAPINFOHEADER lpbmi; // pointer to a Win 3.0-style DIB
LPBITMAPCOREHEADER lpbmc; // pointer to an OS/2-style DIB
/* point to the header (whether OS/2 or Win 3.0 */
lpbmi = (LPBITMAPINFOHEADER)lpDIB;
lpbmc = (LPBITMAPCOREHEADER)lpDIB;
/* return the DIB height if it is a Win 3.0 DIB */
if (lpbmi->biSize == sizeof(BITMAPINFOHEADER))
return lpbmi->biHeight;
else /* it is an OS/2 DIB, so return its height */
return (DWORD)lpbmc->bcHeight;
}
/*************************************************************************
*
* PaletteSize()
*
* Parameter:
*
* LPSTR lpbi - pointer to packed-DIB memory block
*
* Return Value:
*
* WORD - size of the color palette of the DIB
*
* Description:
*
* This function gets the size required to store the DIB's palette by
* multiplying the number of colors by the size of an RGBQUAD (for a
* Windows 3.0-style DIB) or by the size of an RGBTRIPLE (for an OS/2-
* style DIB).
*
************************************************************************/
WORD PaletteSize(LPSTR lpbi)
{
/* calculate the size required by the palette */
if (IS_WIN30_DIB (lpbi))
return (DIBNumColors(lpbi) * sizeof(RGBQUAD));
else
return (DIBNumColors(lpbi) * sizeof(RGBTRIPLE));
}
/*************************************************************************
*
* DIBNumColors()
*
* Parameter:
*
* LPSTR lpbi - pointer to packed-DIB memory block
*
* Return Value:
*
* WORD - number of colors in the color table
*
* Description:
*
* This function calculates the number of colors in the DIB's color table
* by finding the bits per pixel for the DIB (whether Win3.0 or OS/2-style
* DIB). If bits per pixel is 1: colors=2, if 4: colors=16, if 8: colors=256,
* if 24, no colors in color table.
*
************************************************************************/
WORD DIBNumColors(LPSTR lpbi)
{
WORD wBitCount; // DIB bit count
/* If this is a Windows-style DIB, the number of colors in the
* color table can be less than the number of bits per pixel
* allows for (i.e. lpbi->biClrUsed can be set to some value).
* If this is the case, return the appropriate value.
*/
if (IS_WIN30_DIB(lpbi))
{
DWORD dwClrUsed;
dwClrUsed = ((LPBITMAPINFOHEADER)lpbi)->biClrUsed;
if (dwClrUsed)
return (WORD)dwClrUsed;
}
/* Calculate the number of colors in the color table based on
* the number of bits per pixel for the DIB.
*/
if (IS_WIN30_DIB(lpbi))
wBitCount = ((LPBITMAPINFOHEADER)lpbi)->biBitCount;
else
wBitCount = ((LPBITMAPCOREHEADER)lpbi)->bcBitCount;
/* return number of colors based on bits per pixel */
switch (wBitCount)
{
case 1:
return 2;
case 4:
return 16;
case 8:
return 256;
default:
return 0;
}
}
/*************************************************************************
*
* CreateDIBPalette()
*
* Parameter:
*
* HDIB hDIB - specifies the DIB
*
* Return Value:
*
* HPALETTE - specifies the palette
*
* Description:
*
* This function creates a palette from a DIB by allocating memory for the
* logical palette, reading and storing the colors from the DIB's color table
* into the logical palette, creating a palette from this logical palette,
* and then returning the palette's handle. This allows the DIB to be
* displayed using the best possible colors (important for DIBs with 256 or
* more colors).
*
************************************************************************/
HPALETTE CreateDIBPalette(HDIB hDIB)
{
LPLOGPALETTE lpPal; // pointer to a logical palette
HANDLE hLogPal; // handle to a logical palette
HPALETTE hPal = NULL; // handle to a palette
int i, wNumColors; // loop index, number of colors in color table
LPSTR lpbi; // pointer to packed-DIB
LPBITMAPINFO lpbmi; // pointer to BITMAPINFO structure (Win3.0)
LPBITMAPCOREINFO lpbmc; // pointer to BITMAPCOREINFO structure (OS/2)
BOOL bWinStyleDIB; // flag which signifies whether this is a Win3.0 DIB
/* if handle to DIB is invalid, return NULL */
if (!hDIB)
return NULL;
/* lock DIB memory block and get a pointer to it */
lpbi = GlobalLock(hDIB);
/* get pointer to BITMAPINFO (Win 3.0) */
lpbmi = (LPBITMAPINFO)lpbi;
/* get pointer to BITMAPCOREINFO (OS/2 1.x) */
lpbmc = (LPBITMAPCOREINFO)lpbi;
/* get the number of colors in the DIB */
wNumColors = DIBNumColors(lpbi);
/* is this a Win 3.0 DIB? */
bWinStyleDIB = IS_WIN30_DIB(lpbi);
if (wNumColors)
{
/* allocate memory block for logical palette */
hLogPal = GlobalAlloc(GHND, sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) *
wNumColors);
/* if not enough memory, clean up and return NULL */
if (!hLogPal)
{
GlobalUnlock(hDIB);
return NULL;
}
/* lock memory block and get pointer to it */
lpPal = (LPLOGPALETTE)GlobalLock(hLogPal);
/* set version and number of palette entries */
lpPal->palVersion = PALVERSION;
lpPal->palNumEntries = wNumColors;
/* store RGB triples (if Win 3.0 DIB) or RGB quads (if OS/2 DIB)
* into palette
*/
for (i = 0; i < wNumColors; i++)
{
if (bWinStyleDIB)
{
lpPal->palPalEntry[i].peRed = lpbmi->bmiColors[i].rgbRed;
lpPal->palPalEntry[i].peGreen = lpbmi->bmiColors[i].rgbGreen;
lpPal->palPalEntry[i].peBlue = lpbmi->bmiColors[i].rgbBlue;
lpPal->palPalEntry[i].peFlags = 0;
}
else
{
lpPal->palPalEntry[i].peRed = lpbmc->bmciColors[i].rgbtRed;
lpPal->palPalEntry[i].peGreen = lpbmc->bmciColors[i].rgbtGreen;
lpPal->palPalEntry[i].peBlue = lpbmc->bmciColors[i].rgbtBlue;
lpPal->palPalEntry[i].peFlags = 0;
}
}
/* create the palette and get handle to it */
hPal = CreatePalette(lpPal);
/* if error getting handle to palette, clean up and return NULL */
if (!hPal)
{
GlobalUnlock(hLogPal);
GlobalFree(hLogPal);
return NULL;
}
}
/* clean up */
GlobalUnlock(hLogPal);
GlobalFree(hLogPal);
GlobalUnlock(hDIB);
/* return handle to DIB's palette */
return hPal;
}
/*************************************************************************
*
* DIBToBitmap()
*
* Parameters:
*
* HDIB hDIB - specifies the DIB to convert
*
* HPALETTE hPal - specifies the palette to use with the bitmap
*
* Return Value:
*
* HBITMAP - identifies the device-dependent bitmap
*
* Description:
*
* This function creates a bitmap from a DIB using the specified palette.
* If no palette is specified, default is used.
*
************************************************************************/
HBITMAP DIBToBitmap(HDIB hDIB, HPALETTE hPal)
{
LPSTR lpDIBHdr, lpDIBBits; // pointer to DIB header, pointer to DIB bits
HBITMAP hBitmap; // handle to device-dependent bitmap
HDC hDC; // handle to DC
HPALETTE hOldPal = NULL; // handle to a palette
/* if invalid handle, return NULL */
if (!hDIB)
return NULL;
/* lock memory block and get a pointer to it */
lpDIBHdr = GlobalLock(hDIB);
/* get a pointer to the DIB bits */
lpDIBBits = FindDIBBits(lpDIBHdr);
/* get a DC */
hDC = GetDC(NULL);
if (!hDC)
{
/* clean up and return NULL */
GlobalUnlock(hDIB);
return NULL;
}
/* select and realize palette */
if (hPal)
hOldPal = SelectPalette(hDC, hPal, FALSE);
RealizePalette(hDC);
/* create bitmap from DIB info. and bits */
hBitmap = CreateDIBitmap(hDC, (LPBITMAPINFOHEADER)lpDIBHdr, CBM_INIT,
lpDIBBits, (LPBITMAPINFO)lpDIBHdr, DIB_RGB_COLORS)
;
/* restore previous palette */
if (hOldPal)
SelectPalette(hDC, hOldPal, FALSE);
/* clean up */
ReleaseDC(NULL, hDC);
GlobalUnlock(hDIB);
/* return handle to the bitmap */
return hBitmap;
}
/*************************************************************************
*
* BitmapToDIB()
*
* Parameters:
*
* HBITMAP hBitmap - specifies the bitmap to convert
*
* HPALETTE hPal - specifies the palette to use with the bitmap
*
* Return Value:
*
* HDIB - identifies the device-dependent bitmap
*
* Description:
*
* This function creates a DIB from a bitmap using the specified palette.
*
************************************************************************/
HDIB BitmapToDIB(HBITMAP hBitmap, HPALETTE hPal)
{
BITMAP bm; // bitmap structure
BITMAPINFOHEADER bi; // bitmap header
BITMAPINFOHEADER FAR *lpbi; // pointer to BITMAPINFOHEADER
DWORD dwLen; // size of memory block
HANDLE hDIB, h; // handle to DIB, temp handle
HDC hDC; // handle to DC
WORD biBits; // bits per pixel
/* check if bitmap handle is valid */
if (!hBitmap)
return NULL;
/* if no palette is specified, use default palette */
if (hPal == NULL)
hPal = GetStockObject(DEFAULT_PALETTE);
/* fill in BITMAP structure */
GetObject(hBitmap, sizeof(bm), (LPSTR)&bm);
/* calculate bits per pixel */
biBits = bm.bmPlanes * bm.bmBitsPixel;
/* initialize BITMAPINFOHEADER */
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = bm.bmWidth;
bi.biHeight = bm.bmHeight;
bi.biPlanes = 1;
bi.biBitCount = biBits;
bi.biCompression = DIB_RGB_COLORS;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;
/* calculate size of memory block required to store BITMAPINFO */
dwLen = bi.biSize + PaletteSize((LPSTR)&bi);
/* get a DC */
hDC = GetDC(NULL);
/* select and realize our palette */
hPal = SelectPalette(hDC, hPal, FALSE);
RealizePalette(hDC);
/* alloc memory block to store our bitmap */
hDIB = GlobalAlloc(GHND, dwLen);
/* if we couldn't get memory block */
if (!hDIB)
{
/* clean up and return NULL */
SelectPalette(hDC, hPal, TRUE);
RealizePalette(hDC);
ReleaseDC(NULL, hDC);
return NULL;
}
/* lock memory and get pointer to it */
lpbi = (VOID FAR *)GlobalLock(hDIB);
/* use our bitmap info. to fill BITMAPINFOHEADER */
*lpbi = bi;
/* call GetDIBits with a NULL lpBits param, so it will calculate the
* biSizeImage field for us
*/
GetDIBits(hDC, hBitmap, 0, (WORD)bi.biHeight, NULL, (LPBITMAPINFO)lpbi,
DIB_RGB_COLORS);
/* get the info. returned by GetDIBits and unlock memory block */
bi = *lpbi;
GlobalUnlock(hDIB);
/* if the driver did not fill in the biSizeImage field, make one up */
if (bi.biSizeImage == 0)
bi.biSizeImage = WIDTHBYTES((DWORD)bm.bmWidth * biBits) * bm.bmHeight;
/* realloc the buffer big enough to hold all the bits */
dwLen = bi.biSize + PaletteSize((LPSTR)&bi) + bi.biSizeImage;
if (h = GlobalReAlloc(hDIB, dwLen, 0))
hDIB = h;
else
{
/* clean up and return NULL */
GlobalFree(hDIB);
hDIB = NULL;
SelectPalette(hDC, hPal, TRUE);
RealizePalette(hDC);
ReleaseDC(NULL, hDC);
return NULL;
}
/* lock memory block and get pointer to it */
lpbi = (VOID FAR *)GlobalLock(hDIB);
/* call GetDIBits with a NON-NULL lpBits param, and actualy get the
* bits this time
*/
if (GetDIBits(hDC, hBitmap, 0, (WORD)bi.biHeight, (LPSTR)lpbi + (WORD)lpbi
->biSize + PaletteSize((LPSTR)lpbi), (LPBITMAPINFO)lpbi,
DIB_RGB_COLORS) == 0)
{
/* clean up and return NULL */
GlobalUnlock(hDIB);
hDIB = NULL;
SelectPalette(hDC, hPal, TRUE);
RealizePalette(hDC);
ReleaseDC(NULL, hDC);
return NULL;
}
bi = *lpbi;
/* clean up */
GlobalUnlock(hDIB);
SelectPalette(hDC, hPal, TRUE);
RealizePalette(hDC);
ReleaseDC(NULL, hDC);
/* return handle to the DIB */
return hDIB;
}
/*************************************************************************
*
* PalEntriesOnDevice()
*
* Parameter:
*
* HDC hDC - device context
*
* Return Value:
*
* int - number of palette entries on device
*
* Description:
*
* This function gets the number of palette entries on the specified device
*
************************************************************************/
int PalEntriesOnDevice(HDC hDC)
{
int nColors; // number of colors
/* Find out the number of palette entries on this
* device.
*/
nColors = GetDeviceCaps(hDC, SIZEPALETTE);
/* For non-palette devices, we'll use the # of system
* colors for our palette size.
*/
if (!nColors)
nColors = GetDeviceCaps(hDC, NUMCOLORS);
assert(nColors);
return nColors;
}
/*************************************************************************
*
* DIBHeight()
*
* Parameter:
*
* LPSTR lpbi - pointer to packed-DIB memory block
*
* Return Value:
*
* DWORD - height of the DIB
*
* Description:
*
* This function returns a handle to a palette which represents the system
* palette (each entry is an offset into the system palette instead of an
* RGB with a flag of PC_EXPLICIT).
*
************************************************************************/
HPALETTE GetSystemPalette(void)
{
HDC hDC; // handle to a DC
HPALETTE hPal = NULL; // handle to a palette
HANDLE hLogPal; // handle to a logical palette
LPLOGPALETTE lpLogPal; // pointer to a logical palette
int i, nColors; // loop index, number of colors
/* Find out how many palette entries we want. */
hDC = GetDC(NULL);
if (!hDC)
return NULL;
nColors = PalEntriesOnDevice(hDC);
ReleaseDC(NULL, hDC);
/* Allocate room for the palette and lock it. */
hLogPal = GlobalAlloc(GHND, sizeof(LOGPALETTE) + nColors * sizeof(
PALETTEENTRY));
/* if we didn't get a logical palette, return NULL */
if (!hLogPal)
return NULL;
/* get a pointer to the logical palette */
lpLogPal = (LPLOGPALETTE)GlobalLock(hLogPal);
/* set some important fields */
lpLogPal->palVersion = PALVERSION;
lpLogPal->palNumEntries = nColors;
for (i = 0; i < nColors; i++)
{
lpLogPal->palPalEntry[i].peBlue = 0;
*((LPWORD)(&lpLogPal->palPalEntry[i].peRed)) = i;
lpLogPal->palPalEntry[i].peFlags = PC_EXPLICIT;
}
/* Go ahead and create the palette. Once it's created,
* we no longer need the LOGPALETTE, so free it.
*/
hPal = CreatePalette(lpLogPal);
/* clean up */
GlobalUnlock(hLogPal);
GlobalFree(hLogPal);
return hPal;
}